package net.oov.identify.model;

public class NGramModel extends CheckModelAdapter{
	
	private Double minNG;
	private FreqCheck fc;
	private Double valueBuffered;
	
	public NGramModel(FreqCheck fc, Double minNG) {
		super();
		this.fc = fc;
		this.minNG = minNG;
	}
	
	/**
	 * N元统计 N-Gram
	 * P(W) = ∏(i=1..n) P(Wi|Wi-n...Wi-1)
	 * 展开 P(W) = P(W1)P(W2|W1)..P(Wn|W1W2..Wn-1)
	 * 
	 */
	public Double value(StatusNode ct, CharSequence cs) {
		Double p = null;
		for(int i=0;i<cs.length();i++){
			double d1 = 1d;
			double d2 = 1d;
			if(i==0)p=1d;//((double)wcr.freq(cs.subSequence(0, 1)))/numWord;
			if(i!=0)d1=((double)fc.freq(cs.subSequence(0, i+1)))/fc.freq(cs.subSequence(0, i));//左结合率(单字)
			if(i!=cs.length()-1)d2=((double)fc.freq(cs.subSequence(i, cs.length())))/fc.freq(cs.subSequence(i+1, cs.length()));//右结合率(单字)
			p*=(2*d1+d2)/3;//偏向字的左结合率权重

		}
		return p;
	}

	public Boolean check(StatusNode ct, CharSequence cs ) {
		
		valueBuffered = value(ct,cs);
		Boolean ret = minNG <= valueBuffered;
//		if(!ret)wl(cs+",N:"+v);
		return ret;
	}
	
	/**
	 * N元统计 N-Gram 扩展 更利于发现长词
	 * P(W) = ∏(i=1..n) P(Wi|Wi-n...Wi-1)
	 * 展开 P(W) = P(W1)P(W2..Wn|W1)..P(Wn/2..Wn|W1W2..Wn/2)P(W1W2..Wn/2+1|Wn/2+1..Wn)..P(W1W2..Wn-1|Wn)
	 * 
	 */
	public Double value2(CharTree ct, CharSequence cs) {
		Double p = null;
		for(int i=0;i<cs.length()-1;i++){
			if(p==null)p=1d;
			if(i>=cs.length()/2){
				p*=((double)fc.freq(cs))/fc.freq(cs.subSequence(0, i+1));
			}else{
				p*=((double)fc.freq(cs))/fc.freq(cs.subSequence(i+1, cs.length()));
			}

		}
		return p;
	}
	
	public Double value(){
		return valueBuffered;
	}
	
	public static void wl(Object s){
		System.out.println(s);
	}

	public String info(StatusNode ct, CharSequence cs) {
		// TODO Auto-generated method stub
		return null;
	}
	
}
